﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Core.Plugins
{
    class PluginManager
    {
        private static List<IPlugin.IPlugin> lstLoadedPlugins = new List<IPlugin.IPlugin>();

        public static List<IPlugin.IPlugin> LoadPlugins()
        {
            lstLoadedPlugins = new List<IPlugin.IPlugin>();
            List<string> enabledPlugins = Configuration.Configuration.GetEnabledPlugins();

            foreach (string dllFile in enabledPlugins)
            {
                try
                {
                    Assembly asm = Assembly.LoadFile(string.Concat(Configuration.Complementary.path, Configuration.Complementary.pluginsPath, "\\", dllFile));

                    if (asm != null)
                    {
                        Type[] types = asm.GetTypes();
                        ICollection<Type> pluginTypes = new List<Type>();

                        foreach (Type type in types)
                        {
                            if (type.IsInterface || type.IsAbstract)
                                continue;
                            else
                            {
                                Type pluginType = typeof(IPlugin.IPlugin);
                                if (type.GetInterface(pluginType.FullName) != null)
                                    pluginTypes.Add(type);
                            }
                        }

                        foreach (Type type in pluginTypes)
                        {
                            IPlugin.IPlugin plugin = (IPlugin.IPlugin)Activator.CreateInstance(type);
                            lstLoadedPlugins.Add(plugin);
                        }
                    }
                }
                catch
                {
                    Log.Log.LogThisConsole(string.Concat("Error loading ", dllFile));
                }
            }

            return lstLoadedPlugins;
        }

        private static Model.Elements.HttpPacket ThrowPlugins(Model.Elements.HttpPacket packet)
        {
            // Executes the plugins from ring 0 to ring 2
            for (int r = 0; r < 2; r++)
            {
                IPlugin.PluginRing ring = (IPlugin.PluginRing)r;

                for (int i = 0; i < lstLoadedPlugins.Count; i++)
                {
                    IPlugin.IPlugin plugin = lstLoadedPlugins[i];

                    if (plugin.Ring != ring)
                        continue;

                    try
                    {
                        packet = plugin.Start(packet);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(string.Concat("Plugin exception [", plugin.Name, "] ", ex.Message, ".<br/><br/><u>Stacktrace</u>: ", ex.StackTrace));
                    }
                }
            }

            return packet;
        }

        public static Model.Elements.HttpPacket ProcessPlugins(Model.Elements.HttpPacket packet)
        {
            return ThrowPlugins(packet);
        }
    }
}
